//
// Created by 86186 on 2021/12/6.
//

#include "AudioDecoder.h"

void AudioDecoder::decode(string url) {
    if (LOG_DEBUG) LOGD("进入decode函数！")

    av_register_all(); //注册解码器
    avformat_network_init(); //初始化网络

    this->resource = new DecodeResource();
    AVFormatContext *avFormatContext = resource->avFormatContext; //上下文
    if (avformat_open_input(&avFormatContext, url.c_str(), NULL, NULL) != 0) {
        /* @return 0 on success, a negative AVERROR on failure.*/
        if (LOG_DEBUG) LOGE("无法打开对应的资源！！！")
        return;
    }
    if (avformat_find_stream_info(avFormatContext, NULL) < 0) {
        //@return >=0 if OK, AVERROR_xxx on error
        if (LOG_DEBUG) LOGE("find stream info error!!!")
        return;
    }
    for (int i = 0; i < avFormatContext->nb_streams; ++i) {
        if (avFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            resource->streamId = i;
            break;
        }
    }

    if (resource->streamId < 0) {
        if (LOG_DEBUG) LOGE("没有找到音频的stream！！！")
        return;
    }
    resource->avCodecParameters = avFormatContext->streams[resource->streamId]->codecpar; //当前stream的参数
    resource->avCodec = avcodec_find_decoder(resource->avCodecParameters->codec_id); //得到解码器
    if (resource->avCodec == NULL) {
        if (LOG_DEBUG) LOGE("无法找到当前的解码器")
        return;
    }
    resource->avCodecContext = avcodec_alloc_context3(resource->avCodec);
    if (resource->avCodecContext == NULL) {
        if (LOG_DEBUG) LOGE("无法生成avCodecContext！")
        return;
    }

    //将解码器中的数据复制到avCodecContext
    if (avcodec_parameters_to_context(resource->avCodecContext, resource->avCodecParameters) < 0) {
        if (LOG_DEBUG) LOGE("无法复制数据到context中！")
        return;
    }

    //打开解码器
    if (avcodec_open2(resource->avCodecContext, resource->avCodec, 0) != 0) {
        if (LOG_DEBUG) LOGE("无法打开解码器！")
        return;
    }

    if (LOG_DEBUG) LOGD("解码环境创建完成！")

    mutex qMutex;
    condition_variable cv;
    AVPacketQueue *queue = new AVPacketQueue(qMutex, cv);

    volatile bool run = true;
    thread tProducer = thread([&] {
        while (run) {
            AVPacket *avPacket = av_packet_alloc();
            if (av_read_frame(avFormatContext, avPacket) == 0) {
                if (avPacket->stream_index == resource->streamId) {
                    if (LOG_DEBUG) LOGD("解码帧")
                    queue->push(avPacket);
                } else {
                    if (LOG_DEBUG) LOGE("avPacket->stream_index不匹配！")
                    av_packet_free(&avPacket); //释放packet中的数据
                    av_free(avPacket);
                }
            } else {
                if (LOG_DEBUG) LOGE("av_read_frame失败！")
                av_packet_free(&avPacket); //释放packet中的数据
                av_free(avPacket);
                run = false;
            }
        }
    });

    OpenSlPlayer *openSlPlayer = new OpenSlPlayer(queue, this->resource);
    openSlPlayer->play();

    thread tConsumer = thread([&] {
//        while (run || queue->size()>0) { //这种方法有问题，当producer线程结束后就不再被唤醒了
//            unique_lock<mutex> lk(queue->qMutex);
//            queue->cv.wait(lk);
//        }
//        unique_lock<mutex> lk(queue->qMutex);
//        queue->cv.wait(lk, [run] {
//            return !run;
//        });
//        if (LOG_DEBUG) LOGE("生产者线程发出信号，已经解码完成！")
        while (run || queue->size()>0) {
            this_thread::sleep_for(chrono::seconds(1));
        }
        if (LOG_DEBUG) LOGE("消费者线程已经把所有数据消费完成了！")
        openSlPlayer->stop();
    });

//    bool exit = false;
//    uint8_t *buffer = (uint8_t *) av_malloc(44100 * 2 * (16 / 8));
//    OpenSlPlayer openSlPlayer;
//
//    thread tConsumer = thread([&] {
//        if (LOG_DEBUG) LOGD("进入消费者线程！")
//        while (!exit) {
//            auto cur = queue.pop();
//            if (LOG_DEBUG) LOGD("出队！")
//
//            int ret = avcodec_send_packet(resource.avCodecContext, cur); //将AVPacket放入解码器
//            if (ret == 0) {
//                AVFrame *avFrame = av_frame_alloc();
//                ret = avcodec_receive_frame(resource.avCodecContext,
//                                            avFrame); //Return decoded output data from a decoder
//                if (ret == 0) {
//                    if (avFrame->channels > 0 && avFrame->channel_layout == 0) {
//                        avFrame->channel_layout = av_get_default_channel_layout(avFrame->channels);
//                    } else if (avFrame->channels == 0 && avFrame->channel_layout > 0) {
//                        avFrame->channels = av_get_channel_layout_nb_channels(
//                                avFrame->channel_layout);
//                    }
//                    SwrContext *swrContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO,
//                                                                AV_SAMPLE_FMT_S16,
//                                                                avFrame->sample_rate,
//                                                                avFrame->channel_layout,
//                                                                (AVSampleFormat) avFrame->format,
//                                                                avFrame->sample_rate, NULL, NULL);
//                    ret = swr_init(swrContext);
//                    if (ret >= 0) {
//                        int nb = swr_convert(swrContext, &buffer, avFrame->nb_samples,
//                                             (const uint8_t **) avFrame->data,
//                                             avFrame->nb_samples); //@return number of samples output per channel, negative value on error
//                        int outChannels = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
//                        int dataSize =
//                                nb * outChannels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16);
//                        if (LOG_DEBUG) LOGD("解码完成！！！")
//                        openSlPlayer.play(buffer, dataSize);
//                    }
//                    if (swrContext != NULL) {
//                        swr_free(&swrContext);
//                    }
//                }
//                av_frame_free(&avFrame);
//                av_free(avFrame);
//            }
//
//            av_packet_free(&cur);
//            av_free(cur);
//            cur = NULL;
//        }
//    });
    tProducer.join();
    tConsumer.join();
}



